#include "NeoProgressBarPrivate.h"
#include "NeoProgressBar.h"
#include <QPropertyAnimation>

NeoProgressBarPrivate::NeoProgressBarPrivate(QObject *parent)
    : QObject(parent),
      pValue(0),
      pPosition(0),
      pBackgroundColor(Qt::white),
      pProgressColor(Qt::blue),
      pBorderRadius(5),
      pPixelRatio(1),
      pMinimumValue(0),
      pMaximumValue(100),
      pProgressPixmap(QPixmap()),
      pFrameRect(QRect()),
      pTextRect(QRect()),
      pTextPosition(NeoProgressBarType::TextPosition::TextOverProgress),
      pPositionAnimation(new QPropertyAnimation(this, "pPosition", this))
{
    pPositionAnimation->setDuration(1000);
    pPositionAnimation->setEasingCurve(QEasingCurve::InOutQuad);
}

NeoProgressBarPrivate::~NeoProgressBarPrivate() = default;

void NeoProgressBarPrivate::startPositionAnimation(int position)
{
    if (pPositionAnimation->state() == QPropertyAnimation::Running)
    {
        pPositionAnimation->stop();
        pPositionAnimation->setStartValue(pPositionAnimation->currentValue().toInt());
        pPositionAnimation->setEndValue(pValue);
    }
    else
    {
        pPositionAnimation->setStartValue(pValue);
        pPositionAnimation->setEndValue(position);
    }
    pPositionAnimation->start();
}

void NeoProgressBarPrivate::updateWidgetGeometry(QSize size)
{
    NEO_PRIVATE_POINT(NeoProgressBar)
    switch (pTextPosition)
    {
    case NeoProgressBarType::TextPosition::NoText:
    {
        pFrameRect = QRect(0, 0, size.width(), size.height());
        pTextRect = QRect();
        break;
    }
    case NeoProgressBarType::TextPosition::TextOverProgress:
    {
        pFrameRect = QRect(0, 0, size.width(), size.height());
        pTextRect = QRect(0, 0, size.width(), size.height());
        break;
    }
    case NeoProgressBarType::TextPosition::TextOutsideLeft:
    {
        pTextRect = QRect(0, 0, q->fontMetrics().horizontalAdvance(QString::number(100)), q->height());
        pFrameRect = QRect(pTextRect.width(), 0, size.width() - pTextRect.width(), size.height());
        break;
    }
    case NeoProgressBarType::TextPosition::TextOutsideRight:
    {
        pTextRect = QRect(size.width() - q->fontMetrics().horizontalAdvance(QString::number(100)), 0,
                          q->fontMetrics().horizontalAdvance(QString::number(100)), size.height());
        pFrameRect = QRect(0, 0, size.width() - pTextRect.width(), size.height());
        break;
    }
    case NeoProgressBarType::TextPosition::TextOutsideTop:
    {
        pTextRect = QRect(0, 0, size.width(), q->fontMetrics().height());
        pFrameRect = QRect(0, pTextRect.height(), size.width(), size.height() - pTextRect.height());
        break;
    }
    case NeoProgressBarType::TextPosition::TextOutsideBottom:
    {
        pTextRect = QRect(0, size.height() - q->fontMetrics().height(), size.width(), q->fontMetrics().height());
        pFrameRect = QRect(0, 0, size.width(), size.height() - pTextRect.height());
        break;
    }
    default:
        break;
    }
    pPixelRatio = 1.0 * pFrameRect.width() / (pMaximumValue - pMinimumValue);
    if (!pProgressPixmap.isNull())
    {
        pProgressPixmap = pProgressPixmap.scaled(pFrameRect.size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
    }
}

void NeoProgressBarPrivate::drawBackground(QPainter *painter)
{
    painter->save();
    painter->setPen(pBackgroundColor);
    painter->setBrush(pBackgroundColor);
    painter->drawRoundedRect(pFrameRect.adjusted(NEO_RADIUS_ADJUSTED_VALUES), pBorderRadius, pBorderRadius);
    painter->restore();
}

void NeoProgressBarPrivate::drawProgress(QPainter *painter)
{
    if (pPosition - pMinimumValue == 0)
    {
        return;
    }
    painter->save();
    QRect progressRect = QRect(pFrameRect.x(), pFrameRect.y(),
                               pPixelRatio * (pPosition - pMinimumValue), pFrameRect.height());
    if (!pProgressPixmap.isNull())
    {
        QRect pixmapRect = progressRect;
        pixmapRect.moveTopLeft(QPoint(0, 0));
        painter->drawPixmap(progressRect, pProgressPixmap, pixmapRect);
    }
    else
    {
        painter->setPen(pProgressColor);
        painter->setBrush(pProgressColor);
        painter->drawRoundedRect(progressRect, pBorderRadius, pBorderRadius);
    }
    painter->restore();
}

void NeoProgressBarPrivate::drawText(QPainter *painter)
{
    NEO_PRIVATE_POINT(NeoProgressBar)
    painter->save();
    painter->setPen(Qt::black);
    painter->drawText(pTextRect, Qt::AlignCenter, QString::number(pPosition));
    painter->restore();
}